﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using iLangl.Model;

namespace iLangl.LanguageWire.DAL.iLanglDAL.XMLStorage
{
	public class SynchronizedDAL : BaseStorageDAL, ISynchronizedDAL
	{

		public String GetKey(IDuplex duplexobject)
		{
			return string.Format("{0}_{1}", duplexobject.GetType().ToString(), duplexobject.TPIdentity);
		}

		#region ISynchronizedDAL Members

		public SyncedOneWayData SyncObjects()
		{
			SyncedOneWayData syncedData = new SyncedOneWayData();

			Hashtable companies = new Hashtable();
			//Company sync
			foreach (dtoXMLStorage.CompanyRow cr in Storage.Company)
			{
				TimeSpan syncspan = GetSyncSpan(eEntityType.Company, cr.Id);

				if(IsRequiredToSync(syncspan, cr.TimeSpan))
				{
					Company company = DALFacade.Instance.CompanyDAL.ReadCompany(cr.Id);
					companies[cr.Id] = company;

					syncedData.TimeSpans[GetKey(company)] = cr.TimeSpan;
				}
			}

			//Billing Info
			foreach (dtoXMLStorage.BillingInfoRow br in Storage.BillingInfo)
			{
				TimeSpan syncspan = GetSyncSpan(eEntityType.BillingInfo, br.Id);

				if (IsRequiredToSync(syncspan, br.TimeSpan))
				{
					BillingInfo bi = DALFacade.Instance.CompanyDAL.ReadBillingInfo(br.Id);

					syncedData.TimeSpans[GetKey(bi)] = br.TimeSpan;

					if (companies[bi.Company.Id] == null)
					{
						companies[bi.Company.Id] = bi.Company;
					}
					else
					{
						bi.Company = (Company)companies[bi.Company.Id];

					}
				}
			}

			//Contact Info
			foreach (dtoXMLStorage.ContactRow cr in Storage.Contact)
			{
				TimeSpan syncpan = GetSyncSpan(eEntityType.Contact, cr.Id);

				if (IsRequiredToSync(syncpan, cr.TimeSpan))
				{
					Contact contact = DALFacade.Instance.ContactDAL.ReadContact(cr.Id);

					syncedData.TimeSpans[GetKey(contact)] = cr.TimeSpan;

					if (companies[contact.Company.Id] == null)
					{
						companies[contact.Company.Id] = contact.Company;
					}
					else
					{
						contact.Company = (Company)companies[contact.Company.Id];
					}

					Company company = (Company)companies[contact.Company.Id];
					company.AddContact(contact);
				}
 			}

			Hashtable projects = new Hashtable();
			//Project
			foreach (dtoXMLStorage.ProjectRow pr in Storage.Project)
			{
				TimeSpan syncspan = GetSyncSpan(eEntityType.Project, pr.Id);

				if(IsRequiredToSync(syncspan, pr.TimeSpan))
				{
					Project project = DALFacade.Instance.ProjectDAL.ReadProject(pr.Id);
					syncedData.TimeSpans[GetKey(project)] = pr.TimeSpan;
					projects[pr.Id] = project;
				}
			}

			//Translation
			foreach (dtoXMLStorage.TranslationRow tr in Storage.Translation)
			{
				TimeSpan syncspan = GetSyncSpan(eEntityType.Translation, tr.Id);

				if(IsRequiredToSync(syncspan, tr.TimeSpan))
				{
					Translation translation = DALFacade.Instance.TranslationDAL.ReadTranslation(tr.Id);
					syncedData.TimeSpans[GetKey(translation)] = tr.TimeSpan;

					if (projects[translation.Project.Id] == null)
					{
						projects[translation.Project.Id] = translation.Project;
					}
					else
					{
						
						translation.Project = (Project)projects[translation.Project.Id];
					}

					Project project = (Project)projects[translation.Project.Id];
					project.AddTranslation(translation);
				}
			}

			//Content
			foreach (dtoXMLStorage.ContentRow cr in Storage.Content)
			{
				TimeSpan syncspan = GetSyncSpan(eEntityType.Content, cr.Id);

				if (IsRequiredToSync(syncspan, cr.TimeSpan))
				{
					ContentEntity content = DALFacade.Instance.ProjectDAL.ReadContent(cr.Id);
					syncedData.TimeSpans[GetKey(content)] = cr.TimeSpan;

					if (projects[content.Project.Id] == null)
					{
						projects[content.Project.Id] = content.Project;
					}
					else
					{

						content.Project = (Project)projects[content.Project.Id];
					}

					Project project = (Project)projects[content.Project.Id];
					project.AddContent(content);
				}
			}

			IList<Company> lcompanies = new List<Company>();

			foreach(String key in companies.Keys)
			{
				lcompanies.Add( (Company)companies[key]);
			}

			IList<Project> lprojects = new List<Project>();

			foreach(String key in projects.Keys)
			{
				lprojects.Add((Project)projects[key]);
			}

			syncedData.Companies = lcompanies.ToArray();
			syncedData.Projects = lprojects.ToArray();


			//Alerts
			IList<ISerializedAlert> alerts = null;

			TimeSpan alertsyncspan = GetSyncSpan(eEntityType.Alert, String.Empty);

			alerts = DALFacade.Instance.AlertDAL.GetAlerts(alertsyncspan, TimeSpan.MaxValue);

			if(alerts != null)
				syncedData.Alerts = alerts.ToArray();
			syncedData.TimeSpans[eEntityType.Alert] = alertsyncspan;

			return syncedData;
		}

		#endregion


		public void MarkAsSynced(SyncedOneWayData data)
		{
			foreach (Company company in data.Companies)
			{
				SyncCompany(company, data.GetTimeSpan(GetKey(company)));

				if(company.BillingInfo != null)
					SyncBillingInfo(company.BillingInfo, data.GetTimeSpan(GetKey(company.BillingInfo)));

				foreach (Contact contact in company.Contacts)
				{
					SyncContact(contact, data.GetTimeSpan(GetKey(contact)));
				}
			}

			foreach (Project project in data.Projects)
			{
				SyncProject(project, data.GetTimeSpan(GetKey(project)));
				if (project.Contents != null)
					foreach (ContentEntity content in project.Contents)
					{
						SyncContent(content, data.GetTimeSpan(GetKey(content)));
					}

				if (project.Translations != null)
					foreach (Translation translaton in project.Translations)
					{
						SyncTranslation(translaton, data.GetTimeSpan(GetKey(translaton)));
					}
			}

			if((data.Alerts != null)&&(data.Alerts.Length > 0))
				SyncAlerts(data.GetTimeSpan(eEntityType.Alert));
		}



		public void SyncContact(Contact contact, TimeSpan timespan)
		{

			UpdateDeliveryTime(eEntityType.Contact, contact.Id, timespan);
		}

		public void SyncCompany(Company company, TimeSpan timespan)
		{
			UpdateDeliveryTime(eEntityType.Company, company.Id, timespan);
		}

		public void SyncBillingInfo(BillingInfo billingInfo, TimeSpan timespan)
		{
			UpdateDeliveryTime(eEntityType.BillingInfo, billingInfo.Id, timespan);
		}

		public void SyncProject(Project project, TimeSpan timespan)
		{
			UpdateDeliveryTime(eEntityType.Project, project.Id, timespan);
		}

		public void SyncContent(ContentEntity content, TimeSpan timespan)
		{
			UpdateDeliveryTime(eEntityType.Content, content.Id, timespan);
		}

		public void SyncTranslation(Translation translation, TimeSpan timespan)
		{
			UpdateDeliveryTime(eEntityType.Translation, translation.Id, timespan);
		}

		public void SyncAlerts(TimeSpan timespan)
		{
			UpdateDeliveryTime(eEntityType.Translation, String.Empty, timespan);
		}
	}
}
